package com.ibm.risk.irmp.common.utils;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.iv.RandomIvGenerator;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

/**
 * 加密/解密工具类
 */
public class EncryptionUtils {
    //jasypt
    private static String ENCRYPT_KEY = "A0CxDz9oJm2";

    private static int RSA_KEY_LENGTH = 2048;
    private static String STRING_POOL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
////	private static int getRandom(int count) {
////		return (int)Math.round(Math.random() * count);
////	}
//	public static String getRandomString(int length){
//	    StringBuffer sb = new StringBuffer();
//	    int len = STRING_POOL.length();
//	    for (int i = 0; i < length; i++) {
//	        sb.append(STRING_POOL.charAt(getRandom(len-1)));
//	    }
//	    return sb.toString();
//	}

    public static final String DEFAULT_ENCRYPT_KEY = "RApSOx16bYtEsStR";

    public static final String publicKeyString = "publicKeyString";
    public static final String privateKeyString = "privateKeyString";

    /**
     * 随机生成RSA公钥和私钥
     */
    public static HashMap<String, String> getRsaRandomKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        keyPairGen.initialize(RSA_KEY_LENGTH);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 获取公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        // 获取私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        HashMap<String, String> keyMap = new HashMap<String, String>();

        // 获取公钥Base64编码
        keyMap.put(publicKeyString, Base64.encodeBase64String(publicKey.getEncoded()));
        // 获取密钥Base64编码
        keyMap.put(privateKeyString, Base64.encodeBase64String(privateKey.getEncoded()));

        return keyMap;
    }

    /**
     * 通过字符串生成RSA私钥
     */
    public static PrivateKey getRsaPrivateKey(String privateKeyData) {
        PrivateKey privateKey = null;
        try {
            // 将字符串Base64解码
            byte[] decodeKey = Base64.decodeBase64(privateKeyData);
            // 创建x509证书封装类
            PKCS8EncodedKeySpec x509 = new PKCS8EncodedKeySpec(decodeKey);
            // 指定RSA
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            // 生成私钥
            privateKey = keyFactory.generatePrivate(x509);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return privateKey;
    }

    /**
     * 通过字符串生成RSA公钥
     */
    public static PublicKey getRsaPublicKey(String publicKeyData) {
        PublicKey publicKey = null;
        try {
            byte[] decodeKey = Base64.decodeBase64(publicKeyData);
            X509EncodedKeySpec x509 = new X509EncodedKeySpec(decodeKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            publicKey = keyFactory.generatePublic(x509);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return publicKey;
    }

    /**
     * RSA加密
     */
    public static String rsaEncrypt(String data, Key key) {
        try {
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encrypted = cipher.doFinal(data.getBytes());
            return new String(Base64.encodeBase64(encrypted));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * RSA解密
     */
    /*public static String rsaDecrypt(String encrypted, Key key) {
        try {
            byte[] data = Base64.decodeBase64(encrypted);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decrypted = cipher.doFinal(data);
            return new String(decrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }*/

//	/**
//	 *
//	 * AES加密密钥（随机16位字符串）
//	 *
//	 * @return
//	 */
//	public static String getAesRandomPassword() {
//		//String key = "RANDOM16bytesStr";
//		return getRandomString(16);
//	}

    /**
     * AES加密
     *
     * @param textCode
     * @param key
     * @return
     * @throws Exception
     */
    public static String aesEncrypt(String textCode, String key) {
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            int blockSize = cipher.getBlockSize();

            byte[] dataBytes = textCode.getBytes("UTF-8");
            int plaintextLength = dataBytes.length;
            if (plaintextLength % blockSize != 0) {
                plaintextLength = plaintextLength + (blockSize - (plaintextLength % blockSize));
            }

            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(key.getBytes());

            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);

            return Base64.encodeBase64String(encrypted);
            //return new sun.misc.BASE64Encoder().encode(encrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * AES解密
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String aesDecrypt(String data, String key) {
        try {
            //byte[] encrypted1 = new sun.misc.BASE64Decoder().decodeBuffer(data);
            byte[] encrypted = Base64.decodeBase64(data);

            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(key.getBytes());

            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

            byte[] original = cipher.doFinal(encrypted);
            String originalString = new String(original, "UTF-8");
            return originalString;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Map<String, String> sort(Map<String, String> map) {
        Map<String, String> sortedMap = new TreeMap<String, String>(new Comparator<String>() {
            @Override
            public int compare(String key1, String key2) {
                return key1.compareTo(key2);
            }
        });
        sortedMap.putAll(map);
        return sortedMap;
    }

    public static String sha(String value) {
        if (value == null) return null;

        return DigestUtils.sha256Hex((DEFAULT_ENCRYPT_KEY + value).getBytes());
    }

    public static String jasyptEncrypt(String text) {
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword(ENCRYPT_KEY);
        encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256");
        encryptor.setIvGenerator(new RandomIvGenerator());
        encryptor.encrypt("rwahx");

        return encryptor.encrypt(text);
    }

    public static String jasyptDecrypt(String decrypted) {
        StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
        encryptor.setPassword(ENCRYPT_KEY);
        encryptor.setAlgorithm("PBEWithHMACSHA512AndAES_256");
        encryptor.setIvGenerator(new RandomIvGenerator());
        encryptor.encrypt("rwahx");

        return encryptor.decrypt(decrypted);
    }
}
